﻿using System;

namespace Simp.Model.CoreExpressions
{
	/// <summary>Addition of two expressions.</summary>
	[ExpressionName("Addition")]
	public class AdditionExpression : BinaryNumericExpressionBase
	{
		/// <summary>Performs addition.</summary>
		/// <param name="simplificationMode"></param>
		/// <param name="leftInteger"></param>
		/// <param name="leftRational"></param>
		/// <param name="leftReal"></param>
		/// <param name="rightInteger"></param>
		/// <param name="rightRational"></param>
		/// <param name="rightReal"></param>
		/// <returns></returns>
		protected override IExpression SimplifyNumerics(
			SimplificationMode simplificationMode,
			IntegerExpression leftInteger,
			RationalExpression leftRational,
			RealExpression leftReal,
			IntegerExpression rightInteger,
			RationalExpression rightRational,
			RealExpression rightReal)
		{
			if (leftInteger != null && rightInteger != null)
			{
				return new IntegerExpression(leftInteger.Value + rightInteger.Value);
			}
			else if (leftRational != null)
			{
				if (rightInteger != null)
				{
					return RationalExpression.GetRational(
						leftRational.Numerator + rightInteger.Value * leftRational.Denominator,
						leftRational.Denominator);
				}
				else if (rightRational != null)
				{
					return RationalExpression.GetRational(
						leftRational.Numerator * rightRational.Denominator + rightRational.Numerator * leftRational.Denominator,
						leftRational.Denominator * rightRational.Denominator);
				}
			}
			if (leftReal != null)
			{
				if (rightRational != null)
				{
					return new RealExpression(leftReal.Value + (double)rightRational.Numerator / rightRational.Denominator);
				}
				else if (rightReal != null)
				{
					return new RealExpression(leftReal.Value + rightReal.Value);
				}
			}

			return null;
		}

		/// <summary>Addition is commuting.</summary>
		protected override bool IsCommuting
		{
			get { return true; }
		}

		/// <summary>Returns the addition symbol.</summary>
		protected override string OperationSymbol
		{
			get { return "+"; }
		}
	}
}